#include<iostream>
#include<pthread.h>
#include<queue>
#include<unistd.h>
using std::cout;
using std::endl;


namespace zgw
{
    const int gcapa=4;
    template<class T>
    class BlockQueue
    {
    public:
        bool Full(){return _data.size()==_capacity;}
        bool Empty(){return _data.empty();}
        BlockQueue(int capacity=gcapa):_capacity(capacity)
        {
            pthread_mutex_init(&_mutex,nullptr);
            pthread_cond_init(&_consumer,nullptr);
            pthread_cond_init(&_productor,nullptr);
        }

        void Push(const T& getdata)
        {
            pthread_mutex_lock(&_mutex);

            while(Full())
            {
                _pwait++;
                pthread_cond_wait(&_productor,&_mutex);
                //如果满了就进入等待队列，等待中如果遇到signal,并且有锁才会重新申请到锁
                _pwait--;
            }
            _data.push(getdata);
            if(_cwait)
            {
                pthread_cond_signal(&_consumer);
            }
            pthread_mutex_unlock(&_mutex);
        }
        void Get(T*getdata)
        {
            pthread_mutex_lock(&_mutex);

            while(Empty())
            {
                _cwait++;
                pthread_cond_wait(&_consumer,&_mutex);
                _cwait--;
            }
            *getdata=_data.front();
            _data.pop();
            if(_pwait)
            {
                pthread_cond_signal(&_productor);
            }
            pthread_mutex_unlock(&_mutex);
        }
        ~BlockQueue()
        {
            pthread_mutex_destroy(&_mutex);
            pthread_cond_destroy(&_consumer);
            pthread_cond_destroy(&_productor);
        }

    

    
    private:
        int _pwait=0;
        int _cwait=0;
        int _capacity;
        std::queue<T> _data;
        pthread_mutex_t _mutex;
        pthread_cond_t _consumer;  //消费等待队列
        pthread_cond_t _productor;  //生产者等待队列
    };
}

